iT邦幫忙

2023 iThome 鐵人賽

DAY 11
0
Modern Web

前端開發之那些我會的與我不會的技術系列 第 11

React 中的 useState:狀態管理和重新渲染的關鍵

  • 分享至 

  • xImage
  •  

component的狀態保存

我們在先前的第一個範例,有看到使用react提供的hook-useState,來當作狀態的管理。

import { useState } from "react";

function App(props) { // react傳進function component的值稱為props
  const [val, setVal] = useState(0); // react的狀態宣告
  const pulsOne = () => { // 自定義的程式內容
    setVal(val + 1);
  }
	// 呈現的畫面放在return
  return (
    <>
      <h2 id="val">{val}</h2>
      <button id="btn" onClick={pulsOne}>+1</button>
    </>
  )
}

export default App

如果useState改為一般的變數,會有相同的結果?

把useState改為一般變數試試

function App() {
	let val = 0;
  const pulsOne = () => {
    val = val + 1;
    console.log(val);
  }
  return (
    <>
      <h2 id="val">{val}</h2>
      <button id="btn" onClick={pulsOne}>+1</button>
    </>
  )
}

export default App

結果如下圖,奇怪!console明明就有加上去,為什麼畫面還是0
https://ithelp.ithome.com.tw/upload/images/20230926/2016275150nevL9tSy.png
這是因為沒有畫面沒有被更新,useState回傳的第2個變數提供了我們重新渲染的功能,在這邊我們先把渲染當作是重新呼叫一次這個function component,來達到更新畫面的效果。

那我們再試試如果重新渲染過後一般的變數在function component會怎樣

import { useState } from "react";

function App() {
  let val = 0;
  const [stateVal, setStateVal] = useState(0);
  const pulsOne = () => {
		// 使用setStateVal來重新渲染
    setStateVal(stateVal + 1);
    val = val + 1;
    console.log(val);
  }
  return (
    <>
      <h2 id="val">{stateVal}</h2>
      <h2 id="val">{val}</h2>
      <button id="btn" onClick={pulsOne}>+1</button>
    </>
  )
}

export default App

得到如下結果,畫面上還是0,console是1
https://ithelp.ithome.com.tw/upload/images/20230926/20162751eHp3qVahfB.png
會有這樣的結果是因為重新渲染(重新呼叫一次function),變數也被重新宣告又賦值為0

我們可以根據上面的幾項測試了解到function component裡的useState比一般變數多了一些功能

  • 能保留變數的值
  • 重新渲染並更新變數

重新了解useState

知道了useState的功能後,這段落來說明useStat的使用細節。

  • const [val, setVal] = useState(0);

    呼叫useState會回傳一個length為2得陣列,第0的個是變數的值(初始值為呼叫useState帶入的值),第1個則是變更變數值的setter function,這邊使用解構去接回傳的變數。

  • 只能在function component的最上層使用

    import { useState } from "react";
    
    function App({isPass}) {
    	// o 只能在最外層
      const [stateVal, setStateVal] = useState(0);
    	// x 不行條件判斷裡
    	if (isPass) {
    		const [stateVal, setStateVal] = useState(0);
    	}
      const pulsOne = () => {
    		// x 不能在function裡
    		const [stateVal, setStateVal] = useState(0);
      }
      return (
        <>
    			// x 也不能在jsx
    			{const [stateVal, setStateVal] = useState(0);}
          <h2 id="val">{stateVal}</h2>
          <h2 id="val">{val}</h2>
          <button id="btn" onClick={pulsOne}>+1</button>
        </>
      )
    }
    
    export default App
    

    這裡文件有特別提到,hooks不能使用條件讓hooks在某些情形的渲染是有執行,某次重新渲染又沒有執行。這是因為hooks的機制所限制。我們可以想想useState只有回傳一個array,是怎麼能記錄每次state的值,答案是依照useState的順序紀錄在每個function component各自的陣列裡,所以如果變更順序或是更改個數,這個陣列就會對照不起來發生錯誤。

  • 每個function component的狀態是獨立的

import { useState } from "react";

function Counter(props) { // react傳進function component的值稱為props
  const [val, setVal] = useState(0); // react的狀態宣告
  const pulsOne = () => { // 自定義的程式內容
    setVal(val + 1);
  }
	// 呈現的畫面放在return
  return (
    <>
      <h2 id="val">{val}</h2>
      <button id="btn" onClick={pulsOne}>+1</button>
    </>
  )
}
function App() {
	return <>
		<Counter />
		<Counter />
	</>
}
export default App

也就是說我們用了兩次Counter component,各自counter是各自獨立且私有的,只會+到自己的狀態
https://ithelp.ithome.com.tw/upload/images/20230926/201627516WC67DqzXd.png

參考

https://react.dev/learn/state-a-components-memory


上一篇
React JSX 中的事件處理程序:基本介紹和語法範例
下一篇
React 中的 useState:狀態快照
系列文
前端開發之那些我會的與我不會的技術31
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言